package com.jingdianjichi.changerecord.impl;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import com.jingdianjichi.changerecord.annotation.ChangeId;
import com.jingdianjichi.changerecord.annotation.ChangeTag;
import com.jingdianjichi.changerecord.entity.ChangeField;
import com.jingdianjichi.changerecord.entity.ChangeForm;
import com.jingdianjichi.changerecord.entity.ChangeRecord;
import com.jingdianjichi.changerecord.entity.ChangeTable;
import com.jingdianjichi.changerecord.enums.ChangeFormatEnum;
import com.jingdianjichi.changerecord.enums.StrFormatEnum;
import com.jingdianjichi.changerecord.exception.ChangeRecordException;
import com.jingdianjichi.changerecord.properties.ChangeRecordProperties;
import com.jingdianjichi.changerecord.strategy.ChangeRecordStrategy;
import com.jingdianjichi.changerecord.strategy.DictStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.lang.Nullable;

import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 变更记录抽象类
 *
 * @author Hu_bx
 * @date 13:48 2023/9/16
 **/
@RequiredArgsConstructor
@Slf4j
public abstract class AbstractChangeRecordImpl implements ChangeRecordStrategy {

    Filter<Field> fieldFilter = field -> field.isAnnotationPresent(ChangeTag.class);
    Filter<Field> fieldOrIdFilter = field -> field.isAnnotationPresent(ChangeId.class) || field.isAnnotationPresent(ChangeTag.class);

    private final DictStrategy dictStrategy;
    private ChangeRecordProperties changeRecordProperties;

    public void setChangeRecordProperties(ChangeRecordProperties changeRecordProperties) {
        this.changeRecordProperties = changeRecordProperties;
    }

    @Override
    public void createChangeDescribe(ProceedingJoinPoint joinPoint, Object returnBody) {
        TimeInterval timeInterval = new TimeInterval();
        timeInterval.start();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Class<?> returnType = methodSignature.getReturnType();
        if (ObjUtil.isEmpty(returnBody)) {
            log.debug("返回参数为空");
            return;
        }
        // 循环表单详情对象字段
        Field[] fields = ReflectUtil.getFields(returnType, fieldOrIdFilter);
        Optional<Field> changeIdField = Arrays.stream(fields)
                .filter(field -> ObjUtil.isNotEmpty(AnnotationUtil.getAnnotation(field, ChangeId.class)))
                .findFirst();
        if (!changeIdField.isPresent()) {
            log.debug("未生成修改记录,Body无主键 className = {}", returnType.getName());
            return;
        }
        Object newBody = JSONUtil.toBean(JSONUtil.toJsonStr(returnBody), returnType);
        Object changeId = ReflectUtil.getFieldValue(newBody, changeIdField.get());
        ChangeRecord changeRecord = this.getById(changeId);
        // 如果不存在,生成
        if (ObjUtil.isEmpty(changeRecord)) {
            log.debug("不存在变更记录无需处理");
            return;
        }
        // 如果存在,重新匹配新旧对象,生成修改记录
        String standard = changeRecord.getStandard();
        Object oldBody = JSONUtil.toBean(standard, returnType);
        ChangeForm changeForm = new ChangeForm();
        log.debug("变更记录处理之前,耗时 = {}", timeInterval.intervalMs());
        timeInterval.restart();
        // 生成修改记录
        createChangeForm(changeForm, fields, newBody, oldBody != null ? oldBody : ReflectUtil.newInstance(returnType));
        log.debug("生成变更记录成功,耗时 = {}", timeInterval.intervalMs());
        timeInterval.restart();

        // 格式化变更记录
        List<String> describe = CollUtil.newArrayList();
        createDescribe(changeForm, describe);
        log.debug("格式化变更记录完成,耗时 = {}", timeInterval.intervalMs());
        changeRecord
                .setChangeData(JSONUtil.toJsonStr(newBody))
                .setDescribe(JSONUtil.toJsonStr(describe));
        this.createChangeDescribeCallBack(changeRecord, returnType);
    }


    @Override
    public Object createChangeRecord(ProceedingJoinPoint joinPoint, Object returnBody) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Class<?> returnType = methodSignature.getReturnType();
        if (ObjUtil.isEmpty(returnBody)) {
            log.debug("返回参数为空");
            throw new ChangeRecordException("返回参数为空");
        }
        // 循环表单详情对象字段
        Field[] fields = ReflectUtil.getFields(returnType, fieldOrIdFilter);
        Optional<Field> changeIdField = Arrays.stream(fields)
                .filter(field -> ObjUtil.isNotEmpty(AnnotationUtil.getAnnotation(field, ChangeId.class)))
                .findFirst();
        if (!changeIdField.isPresent()) {
            log.debug("未生成修改记录,Body无主键 className = {}", returnType.getName());
            throw new ChangeRecordException("未生成修改记录");
        }
        Object newBody = JSONUtil.toBean(JSONUtil.toJsonStr(returnBody), returnType);
        Object changeId = ReflectUtil.getFieldValue(newBody, changeIdField.get());
        if (ObjUtil.isEmpty(changeId)) {
            log.debug("未生成修改记录,Body主键为空 className = {}", returnType.getName());
            throw new ChangeRecordException("未生成修改记录");
        }
        ChangeRecord changeRecord = this.getById(changeId);
        // 存在则直接返回初始数据
        if (ObjUtil.isNotEmpty(changeRecord) && StrUtil.isNotBlank(changeRecord.getStandard())) {
            Object toBean = JSONUtil.toBean(changeRecord.getStandard(), returnType);
            Arrays.stream(fields).forEach(field -> setFieldNewValue(newBody, toBean, field));
            return toBean;
        }
        if (ObjUtil.isEmpty(changeRecordProperties) || changeRecordProperties.getIsFillNewId()) {
            // 没有则处理 新ID,保存
            Arrays.stream(fields).forEach(field -> resetChildNewId(newBody, field));
        }
        changeRecord = new ChangeRecord()
                .setId(changeId.toString())
                .setStandard(JSONUtil.toJsonStr(newBody));
        // 回调用于保存或其他处理
        this.createChangeRecordCallBack(changeRecord, returnType);
        return newBody;
    }

    /**
     * 设置新值
     *
     * @param newBody newBody
     * @param oldBody oldBody
     * @param field   field
     * @author Hu_bx
     * @date 10:11 2023/3/17
     **/
    @Override
    public void setFieldNewValue(Object newBody, Object oldBody, Field field) {
        if (ObjUtil.isEmpty(newBody) || ObjUtil.isEmpty(oldBody)) {
            return;
        }
        Object oldField = ReflectUtil.getFieldValue(oldBody, field);
        Object newField = ReflectUtil.getFieldValue(newBody, field);
        if (ObjUtil.isEmpty(newField) || ObjUtil.isEmpty(field)) {
            return;
        }
        ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
        if (ObjUtil.isNotEmpty(changeTag) && ClassUtil.isSimpleValueType(field.getType()) && changeTag.isFillNewValue()) {
            ReflectUtil.setFieldValue(oldBody, field, newField);
            return;
        }
        if (oldField instanceof Collection) {
            Collection<?> oldFieldColl = (Collection<?>) oldField;
            Collection<?> newFieldColl = (Collection<?>) newField;
            // todo 暂不处理集合
            return;
        }
        Field[] fields = ReflectUtil.getFields(oldField.getClass(), fieldOrIdFilter);
        Arrays.stream(fields).forEach(f -> setFieldNewValue(newField, oldField, f));
    }

    /**
     * 重置主键id
     *
     * @param type    type
     * @param newBody newBody
     */
    private void resetNewId(Class<?> type, Object newBody) {
        Field[] fields = ReflectUtil.getFields(type, fieldOrIdFilter);
        Arrays.stream(fields).forEach(field -> {
            ChangeId changeId = AnnotationUtil.getAnnotation(field, ChangeId.class);
            if (changeId != null && changeId.isFillNewId()) {
                ReflectUtil.setFieldValue(newBody, field, generateId(newBody, field));
                return;
            }
            resetChildNewId(newBody, field);
        });
    }

    /**
     * 重置主键id
     *
     * @param field   field
     * @param newBody newBody
     */
    @Override
    public void resetChildNewId(Object newBody, Field field) {
        Object newField = ReflectUtil.getFieldValue(newBody, field);
        if (ObjUtil.isEmpty(newField) || ClassUtil.isSimpleValueType(field.getType())) {
            return;
        }
        if (newField instanceof Collection) {
            Collection<?> newFieldColl = (Collection<?>) newField;
            for (Object o : newFieldColl) {
                resetNewId(o.getClass(), o);
            }
            ReflectUtil.setFieldValue(newBody, field, newFieldColl);
            return;
        }
        resetNewId(field.getType(), newField);
        ReflectUtil.setFieldValue(newBody, field, newField);
    }

    @Override
    public Object generateId(Object newBody, Field field) {
        return IdUtil.fastSimpleUUID();
    }

    /**
     * 创建修改表单详情
     *
     * @param changeForm changeForm
     * @param fields     fields
     * @param newBody    newBody
     * @param oldBody    oldBody
     * @author Hu_bx
     * @date 15:12 2022/11/10
     **/
    @Override
    public void createChangeForm(ChangeForm changeForm, Field[] fields, Object newBody, Object oldBody) {
        if (ObjUtil.isEmpty(fields)) {
            return;
        }
        for (Field field : fields) {
            Object newField = ReflectUtil.getFieldValue(newBody, field);
            Object oldField = ReflectUtil.getFieldValue(oldBody, field);
            // 判断是否处理
            if (isChange(field, newField, oldField)) {
                continue;
            }
            // 处理基础类型字段
            if (ClassUtil.isSimpleValueType(field.getType())) {
                createSimpleChangeField(changeForm, newField, oldField, field);
                continue;
            }
            ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
            // 处理集合类型字段
            if (newField instanceof Collection || oldField instanceof Collection) {
                createChangeTable(changeForm, newField, oldField, field);
                continue;
            }

            // 处理子对象,递归处理对象中字段
            Class<?> type = field.getType();
            Field[] childField = ReflectUtil.getFields(type, fieldFilter);
            //  子ChangeForm可能是多个,后续有需要改成集合
            ChangeForm childForm = ObjUtil.isEmpty(changeForm.getChangeForm()) ? new ChangeForm() : changeForm.getChangeForm();
            childForm.setLabel(changeTag.value());
            createChangeForm(childForm, childField, newField, oldField != null ? oldField : ReflectUtil.newInstance(type));
            changeForm.setChangeForm(childForm);
        }
    }

    /**
     * 创建详情
     *
     * @param childForm childForm
     * @param content   content
     * @author Hu_bx
     * @date 14:26 2022/11/11
     **/
    @Override
    public void createDescribe(ChangeForm childForm, List<String> content) {
        // 字段
        if (ObjUtil.isNotEmpty(childForm.getFieldList())) {
            List<String> fieldContent = childForm.getFieldList().stream()
                    .filter(changeField -> !changeField.getIsTableTag() && ObjUtil.notEqual(changeField.getOldFormatValue(), changeField.getNewFormatValue()))
                    .filter(changeField -> !changeField.getIsTableTag() && ObjUtil.notEqual(changeField.getOldValue(), changeField.getNewValue()))
                    .map(changeField -> StrFormatEnum.CHANGE_FIELD_CHANGE.format(changeField.getLabel(),
                            changeField.getOldFormatValue(), changeField.getNewFormatValue()))
                    .collect(Collectors.toList());

            List<String> target = childForm.getFieldList().stream()
                    .filter(ChangeField::getIsTableTag)
                    .map(changeField -> StrUtil.toString(changeField.getNewFormatValue()))
                    .collect(Collectors.toList());
            // 如果存在修改字典,添加记录
            if (ObjUtil.isNotEmpty(fieldContent)) {
                if (StrUtil.isBlank(childForm.getLabel())) {
                    content.add(StrFormatEnum.CHANGE_FORM_CHANGE.format(StrUtil.join(StrPool.COMMA, fieldContent)));
                } else {
                    String label = ObjUtil.isEmpty(target) ? childForm.getLabel() : childForm.getLabel() + StrUtil.DASHED + CollUtil.join(target, StrUtil.COMMA);
                    String format = StrFormatEnum.CHANGE_FORM_LABEL_CHANGE.format(label, StrUtil.join(StrPool.COMMA, fieldContent));
                    content.add(format);
                }
            }
        }
        // 表格
        if (ObjUtil.isNotEmpty(childForm.getTableList())) {
            childForm.getTableList().forEach(table -> {
                // 处理修改的列表
                table.getChangeFormList().stream().filter(changeForm -> changeForm.getType()
                        .equals(ChangeForm.Type.UPDATE)).forEach(changeForm -> createDescribe(changeForm, content));
                if (table.getSaveRowNum() != 0) {
                    // 处理添加的
                    List<String> tagSaveList = table.getChangeFormList().stream()
                            .filter(changeForm -> changeForm.getType()
                                    .equals(ChangeForm.Type.SAVE)).map(this::getSaveString)
                            .filter(ObjUtil::isNotEmpty).collect(Collectors.toList());
                    String format = StrFormatEnum.CHANGE_TABLE_SAVE_NUM.format(table.getSaveRowNum(), table.getLabel(), StrUtil.join(StrPool.COMMA, tagSaveList));
                    log.debug(format);
                    content.add(format);
                }
                if (table.getDeleteRowNum() != 0) {
                    // 处理删除的
                    List<String> tagDeleteList = table.getChangeFormList().stream()
                            .filter(changeForm -> changeForm.getType()
                                    .equals(ChangeForm.Type.DELETE)).map(this::getDeleteString)
                            .filter(ObjUtil::isNotEmpty).collect(Collectors.toList());
                    String format = StrFormatEnum.CHANGE_TABLE_DELETE_NUM.format(table.getDeleteRowNum(), table.getLabel(), StrUtil.join(StrPool.COMMA, tagDeleteList));
                    log.debug(format);
                    content.add(format);
                }
            });
        }
        // 子表单
        if (ObjUtil.isNotEmpty(childForm.getChangeForm())) {
            createDescribe(childForm.getChangeForm(), content);
        }
    }

    /**
     * 生成新增描述
     *
     * @param changeForm changeForm
     * @return java.lang.String
     * @author Hu_bx
     * @date 18:27 2023/9/15
     **/
    @Nullable
    public String getSaveString(ChangeForm changeForm) {
        List<String> tag = changeForm.getFieldList().stream().filter(ChangeField::getIsTableTag)
                .map(changeField -> StrUtil.format("[{}]", changeField.getNewFormatValue()))
                .filter(ObjUtil::isNotEmpty)
                .collect(Collectors.toList());
        return ObjUtil.isEmpty(tag) ? null : StrUtil.join(StrPool.UNDERLINE, tag);
    }

    /**
     * 生成删除描述
     *
     * @param changeForm changeForm
     * @return java.lang.String
     * @author Hu_bx
     * @date 18:27 2023/9/15
     **/
    @Nullable
    public String getDeleteString(ChangeForm changeForm) {
        List<String> tag = changeForm.getFieldList().stream().filter(ChangeField::getIsTableTag)
                .map(changeField -> StrUtil.format("[{}]", changeField.getOldFormatValue()))
                .filter(ObjUtil::isNotEmpty)
                .collect(Collectors.toList());
        return ObjUtil.isEmpty(tag) ? null : StrUtil.join(StrPool.UNDERLINE, tag);
    }

    /**
     * 字段是否需要处理修改
     *
     * @param field    field
     * @param newField newField
     * @param oldField oldField
     * @return boolean
     * @author Hu_bx
     * @date 19:11 2022/11/10
     **/
    private boolean isChange(Field field, Object newField, Object oldField) {
        ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
        if (ObjUtil.isEmpty(changeTag)) {
            return true;
        }
        if (ObjUtil.isNotEmpty(changeTag) && changeTag.exclude()) {
            return true;
        }
        return newField == null && oldField == null;
    }

    /**
     * 创建基础类型字段
     *
     * @param changeForm changeForm
     * @param newField   newField
     * @param oldField   oldField
     * @param field      field
     */
    @Override
    public void createSimpleChangeField(ChangeForm changeForm, Object newField,
                                        Object oldField, Field field) {

        ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
        // 获取新对象 和 旧对象值是否相同,不同则记录
        if (ObjUtil.equal(oldField, newField) && !changeTag.isTableTag()) {
            return;
        }

        ChangeField changeField = new ChangeField()
                .setOldValue(StrUtil.toString(oldField))
                .setIsTableTag(ObjUtil.isNotEmpty(changeTag) && changeTag.isTableTag())
                .setLabel(changeTag.value())
                .setNewValue(StrUtil.toString(newField))
                .setFieldName(field.getName());
        // 如果changeTag不为空,优先取changeTag
        // 如果关联字典,优先取字典数据,如果处理格式化
        if (!StrUtil.EMPTY.equals(changeTag.dict()) && ChangeFormatEnum.AUTO.equals(changeTag.format())) {
            // 是否关联字典,不关联字典,则直接赋值为format
            // 获取字典值
            String oldDict = dictStrategy.getDictByCode(changeTag.dict(), StrUtil.toString(oldField));
            String newDict = dictStrategy.getDictByCode(changeTag.dict(), StrUtil.toString(newField));
            changeField.setOldFormatValue(StrUtil.isBlank(oldDict) ? ChangeFormatEnum.NULL : oldDict)
                    .setNewFormatValue(StrUtil.isBlank(newDict) ? ChangeFormatEnum.NULL : newDict);
        } else if (ChangeFormatEnum.AUTO.equals(changeTag.format())) {
            // 枚举策略进行格式化值，可自定义换为策略类
            changeField.setOldFormatValue(ChangeFormatEnum.formatDefault(oldField, field))
                    .setNewFormatValue(ChangeFormatEnum.formatDefault(newField, field));
        } else {
            // 如果无字典,且不是默认格式化，走自定义格式化
            changeField.setOldFormatValue(formatValue(oldField, changeTag, field))
                    .setNewFormatValue(formatValue(newField, changeTag, field));
        }
        if (ObjUtil.equal(changeField.getNewFormatValue(), changeField.getOldFormatValue()) && !changeTag.isTableTag()) {
            log.debug("{} 由 {}修改为{}格式化后值一样,无需处理", changeField.getLabel(), changeField.getOldFormatValue(), changeField.getNewFormatValue());
            return;
        }
        log.debug("{} 由 {}修改为{}", changeField.getLabel(), changeField.getOldFormatValue(), changeField.getNewFormatValue());
        List<ChangeField> fieldList = ObjUtil.isEmpty(changeForm.getFieldList()) ? CollUtil.newArrayList() : changeForm.getFieldList();
        fieldList.add(changeField);
        changeForm.setFieldList(fieldList);
    }

    /**
     * 创建修改表格详情
     *
     * @param changeForm changeForm
     * @param newField   newField
     * @param oldField   oldField
     * @author Hu_bx
     * @date 15:12 2022/11/10
     **/
    @Override
    public void createChangeTable(ChangeForm changeForm, Object newField, Object oldField, Field field) {
        Collection<?> newFieldColl = newField == null ? CollUtil.newArrayList() : (Collection<?>) newField;
        Collection<?> oldBodyColl = oldField == null ? CollUtil.newArrayList() : (Collection<?>) oldField;
        ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
        // 填充行数
        ChangeTable changeTable = new ChangeTable()
                .setLabel(changeTag.value())
                .setFieldName(field.getName());
        putTableNum(changeTable, newFieldColl, oldBodyColl);
        changeForm.getTableList().add(changeTable);
        putTableField(newFieldColl, oldBodyColl, changeTable);
    }

    /**
     * 填充表格参数
     *
     * @param newFieldColl newFieldColl
     * @param oldBodyColl  oldBodyColl
     * @param changeTable  changeTable
     * @author Hu_bx
     * @date 17:28 2022/11/10
     **/
    @Override
    public void putTableField(Collection<?> newFieldColl, Collection<?> oldBodyColl, ChangeTable changeTable) {
        // 行数处理结束,处理相同行的字段匹配
        Optional<?> oldOptional = oldBodyColl.stream().findFirst();
        Optional<?> newOptional = newFieldColl.stream().findFirst();
        if (!oldOptional.isPresent() && !newOptional.isPresent()) {
            return;
        }
        Object table = oldOptional.isPresent() ? oldOptional.get() : newOptional.get();
        Field[] fieldIds = ReflectUtil.getFields(table.getClass(), field -> field.isAnnotationPresent(ChangeId.class));
        Optional<Field> changeIdField = Arrays.stream(fieldIds).findFirst();
        if (!changeIdField.isPresent()) {
            return;
        }
        // 旧的有新的没有-> 删除 |新的有旧的没有->新增
        // 转集合为 id<->对象,的map,跟基准对象做比较,基准对象在新对象中存在的才比较,不存在的为新增数据不做比较
        Map<Object, ?> newFieldMap = newFieldColl.stream()
                .collect(Collectors.toMap(newTable -> ReflectUtil.getFieldValue(newTable, changeIdField.get()), Function.identity()));
        for (Object oldT : oldBodyColl) {
            // 旧的获取新的
            Object fieldValue = ReflectUtil.getFieldValue(oldT, changeIdField.get());
            Object newF = newFieldMap.get(fieldValue);

            //基准对象在新对象中存在的才比较
            if (ObjUtil.isEmpty(newF)) {
                // 旧的有新的没有-> 删除
                Field[] childField = ReflectUtil.getFields(oldT.getClass(), fieldFilter);
                ChangeForm childForm = new ChangeForm().setLabel(changeTable.getLabel())
                        .setType(ChangeForm.Type.DELETE);
                Arrays.stream(childField)
                        .forEach(field -> createSimpleChangeField(childForm, null, ReflectUtil.getFieldValue(oldT, field), field));
                changeTable.getChangeFormList().add(childForm);
                newFieldMap.remove(fieldValue);
                continue;
            }
            // 如果是对象,递归处理对象中字段
            Field[] childField = ReflectUtil.getFields(oldT.getClass(), fieldFilter);
            ChangeForm childForm = new ChangeForm().setLabel(changeTable.getLabel()).setType(ChangeForm.Type.UPDATE);
            createChangeForm(childForm, childField, newF, oldT);
            changeTable.getChangeFormList().add(childForm);
            newFieldMap.remove(fieldValue);
        }

        // 新的有旧的没有 - >新增
        newFieldMap.forEach((k, newF) -> {
            ChangeForm childForm = new ChangeForm().setLabel(changeTable.getLabel()).setType(ChangeForm.Type.SAVE);
            Field[] childField = ReflectUtil.getFields(newF.getClass(), fieldFilter);
            Arrays.stream(childField)
                    .forEach(field -> createSimpleChangeField(childForm, ReflectUtil.getFieldValue(newF, field), null, field));
            changeTable.getChangeFormList().add(childForm);
        });
    }

    /**
     * 填充表格行数
     *
     * @param newFieldColl newFieldColl
     * @param oldBodyColl  oldBodyColl
     * @author Hu_bx
     * @date 17:28 2022/11/10
     **/
    @Override
    public void putTableNum(ChangeTable changeTable, Collection<?> newFieldColl,
                            Collection<?> oldBodyColl) {
        // 获取新对象 和 旧对象值是否相同,不同则记录
        changeTable.setNewRowNum(newFieldColl.size())
                .setOldRowNum(oldBodyColl.size());
        // 如果新表格不存在,则为删除了,保存删除行数
        if (CollUtil.isEmpty(newFieldColl)) {
            log.debug("{} 删除 {}条", changeTable.getLabel(), oldBodyColl.size());
            changeTable.setDeleteRowNum(oldBodyColl.size());
        }
        // 如果旧表格不存在,则为新增了,保存新增行数
        if (CollUtil.isEmpty(oldBodyColl)) {
            log.debug("{} 新增 {}条", changeTable.getLabel(), newFieldColl.size());
            changeTable.setSaveRowNum(newFieldColl.size());
        }
        // 如果都存在,则相减计算行数
        if (CollUtil.isNotEmpty(oldBodyColl) && CollUtil.isNotEmpty(newFieldColl)) {
            if (NumberUtil.compare(newFieldColl.size(), oldBodyColl.size()) >= 0) {
                log.debug("{} 新增 {}条", changeTable.getLabel(), newFieldColl.size() - oldBodyColl.size());
                changeTable.setSaveRowNum(newFieldColl.size() - oldBodyColl.size());
            } else {
                log.debug("{} 删除 {}条", changeTable.getLabel(), oldBodyColl.size() - newFieldColl.size());
                changeTable.setDeleteRowNum(oldBodyColl.size() - newFieldColl.size());
            }
        }
    }

    @Override
    public String formatValue(Object value, ChangeTag changeTag, Field field) {
        return changeTag.format().format(value, field);
    }
}
